package pub.cleangao.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * 方法类
 */
public class ReflectUtil {

    private ReflectUtil() {
        super();
    }

    /**
     * 循环向上转型, 获取对象的所有的DeclaredField
     *
     * @param clazz : 子类对象
     * @return 父类中的属性对象
     */

    public static List<Field> getDeclaredFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    // 过滤static字段
                    if (Modifier.isStatic(field.getModifiers())) {
                        continue;
                    }
                    fieldList.add(field);
                }
            } catch (Exception e) {
                // 这里什么都不要做！并且这里的异常必须这样写，不能抛出去。
                // 如果这里的异常打印或者往外抛，则就不会执行clazz =
                // clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }
        return fieldList;
    }

    /**
     * 循环向上转型, 获取对象的 DeclaredField
     *
     * @param object    : 子类对象
     * @param fieldName : 父类中的属性名
     * @return 父类中的属性对象
     */

    public static Field getDeclaredField(Object object, String fieldName) {
        Class<?> clazz = object.getClass();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                return clazz.getDeclaredField(fieldName);
            } catch (Exception e) {
                // 这里什么都不要做！并且这里的异常必须这样写，不能抛出去。
                // 如果这里的异常打印或者往外抛，则就不会执行clazz =
                // clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }
        return null;
    }


    /**
     * 获取对象中某一字段的值
     *
     * @param object    指定对象
     * @param fieldName 字段名称
     */
    public static Object getFieldValue(Object object, String fieldName) {
        Field field = getDeclaredField(object, fieldName);
        if (field == null) {
            return null;
        }
        makeAccessible(field);
        try {
            return field.get(object);
        } catch (IllegalAccessException e) {
            return null;
        }
    }


    /**
     * 将字段设置为可见
     *
     * @param field 字段
     */
    public static void makeAccessible(Field field) {
        if ((!Modifier.isPublic(field.getModifiers()) ||
                !Modifier.isPublic(field.getDeclaringClass().getModifiers()) ||
                Modifier.isFinal(field.getModifiers()))) {
            field.setAccessible(true);
        }
    }


}
